<template>
  <div>
    <el-header>
      <el-page-header @back="goBack" content="租赁合同签署" class="page-header"></el-page-header>
    </el-header>
    <el-container class="container">
      <el-main>
        <el-steps :active="activeStep" finish-status="success" align-center>
          <el-step title="资料核对"></el-step>
          <el-step title="合同生成"></el-step>
          <el-step title="合同签署"></el-step>
        </el-steps>
        <div v-if="activeStep === 0">
          <h4 style="text-align: center; margin-bottom: 20px">请核对相关资料后，点击下一步</h4>
          <el-form :model="tenantInfo" label-width="120px">
            <el-form-item label="姓名">
              <el-input v-model="tenantInfo.name" disabled></el-input>
            </el-form-item>
            <el-form-item label="身份证号">
              <el-input v-model="tenantInfo.idNumber" disabled></el-input>
            </el-form-item>
            <el-form-item label="性别">
              <el-select v-model="tenantInfo.gender" disabled style="width: 100%">
                <el-option label="男" value="male"></el-option>
                <el-option label="女" value="female"></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="套房信息">
              <el-input v-model="tenantInfo.apartmentInfo" disabled></el-input>
            </el-form-item>
            <el-form-item label="租金">
              <el-input v-model="tenantInfo.rent" disabled></el-input>
            </el-form-item>
            <el-button class="next-button" type="primary" @click="nextStep">下一步</el-button>
          </el-form>
        </div>
        <div v-if="activeStep === 1">
          <h4 style="text-align: center; margin-bottom: 20px">请确认合同信息</h4>
          <el-card>
            <h3>租赁合同</h3>
            <p>
              出租方（甲方）：
              <u>{{ lessorInfo.lessorName }}</u>
            </p>
            <p>
              承租方（乙方）：
              <u>{{ tenantInfo.name }}</u>
            </p>
            <p>
              身份证号：
              <u>{{ tenantInfo.idNumber }}</u>
            </p>
            <p>
              性别：
              <u>{{ tenantInfo.gender }}</u>
            </p>
            <p>
              套房信息：
              <u>{{ tenantInfo.apartmentInfo }}</u>
            </p>
            <p>
              租金：
              <u>{{ tenantInfo.rent }}</u> 元/月
            </p>
            <p>
              合同期限：
              <u>{{ lessorInfo.leaseTerm }} 年</u>
            </p>
            <p>
              起始时间：
              <u>{{ startDate }}</u>
            </p>
            <p>
              甲方联系方式：
              <u>{{ lessorInfo.lessorPhone }}</u>
            </p>
            <p>
              乙方联系方式：
              <u>{{ tenantInfo.phone }}</u>
            </p>
            <p>甲乙双方经协商一致，达成如下协议：</p>
            <ol>
              <li>
                租赁期限为{{ lessorInfo.leaseTerm }}年，自
                <u>{{ startDate }}</u>起至
                <u>{{ endDate }}</u>止。
              </li>
              <li>
                租金为每月
                <u>{{ tenantInfo.rent }}</u>元，乙方应于每月5日前支付当月租金。
              </li>
              <li>乙方不得擅自转租、转借房屋。</li>
              <li>租赁期间，乙方应保持房屋及其附属设施的完好，因乙方使用不当造成的损坏由乙方负责维修。</li>
              <li>合同期满后，如甲乙双方无异议，可续签合同。</li>
            </ol>
            <span>
              甲方签字（章）：
              <img
                :src="require(`@/assets/seal.png`)"
                style="width:150px;height:150px"
                alt="甲方签字"
              />
            </span>
            <span style="margin-left: 100px">乙方签字：________________</span>
            <el-button class="next-button" type="primary" @click="nextStep">下一步</el-button>
          </el-card>
        </div>
        <div v-if="activeStep === 2">
          <h4 style="text-align: center; margin-bottom: 20px">请签名并输入密码以完成租赁</h4>
          <p>请在下方区域进行签名！</p>
          <p>签名完成请点击保存按钮，若签名错误请点取消清空</p>
          <div class="ml_sign">
            <canvas ref="signature" id="signature"></canvas>
            <div class="btn-wrapper">
              <el-button @click="clear">取消</el-button>
              <el-button @click="save">保存</el-button>
            </div>
            <img :src="imgurl" />
          </div>
          <el-form :model="signInfo" label-width="120px">
            <el-form-item label="验证登录密码">
              <el-input type="password" v-model="signInfo.password"></el-input>
            </el-form-item>
            <el-button class="next-button" type="primary" @click="signContract">签署合同</el-button>
          </el-form>
        </div>
      </el-main>
    </el-container>
  </div>
</template>
  
  <script>
export default {
  name: "Signatrue",
  data() {
    return {
      activeStep: 0,
      tenantInfo: {},
      signInfo: {
        password: ""
      },
      startDate: this.calculateStartDate(),
      endDate: this.calculateEndDate(),
      lessorInfo: {
        lessorName: "杨鑫公租房租赁有限公司",
        lessorPhone: "010-82561234",
        leaseTerm: "2"
      },
      canvas: null, // 存储canvas节点
      ctx: null, // 存储canvas的context上下文
      config: {
        width: 400, // 宽度
        height: 200, // 高度
        strokeStyle: "red", // 线条颜色
        lineWidth: 4, // 线条宽度
        lineCap: "round", // 设置线条两端圆角
        lineJoin: "round" // 线条交汇处圆角
      },
      points: [], // 记录坐标 用来判断是否有签名的
      client: {
        offsetX: 0, // 偏移量
        offsetY: 0,
        endX: 0, // 坐标
        endY: 0
      },
      imgurl: "", // 签名图片
      isDrawing: false, // 用来控制是否正在绘制
      points: [], // 记录签名点的坐标
      steps: [] // 用来存储绘制过程中的每一步
    };
  },
  computed: {
    // 判断是否为移动端
    mobileStatus() {
      return /Mobile|Android|iPhone/i.test(navigator.userAgent);
    }
  },
  mounted() {
    this.getTenantInfo();
  },
  methods: {
    goBack() {
      this.$router.go(-1);
    },
    getTenantInfo() {
      this.$axios
        .get("/contract/getContractInfo", {
          params: { account: this.$store.state.loginTenant.account }
        })
        .then(res => {
          if (res.data.code === 500) {
            this.$message.error(res.data.message);
            this.$router.go(-1);
            return;
          }
          const data = res.data.data;
          this.tenantInfo = {
            ...data,
            apartmentInfo: data.areaName + data.communityName + data.roomNumber
          };
        });
    },
    nextStep() {
      this.activeStep++;
    },
    signContract() {
      if (!this.signInfo.password) {
        this.$message.error("请输入登录密码");
        return;
      }
      this.$confirm("签署合同后，将无法撤销租赁，是否继续？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          this.$axios
            .post("/contract/signContract", {
              ...this.tenantInfo,
              ...this.lessorInfo,
              startDate: this.startDate,
              endDate: this.endDate,
              password: this.signInfo.password
            })
            .then(res => {
              if (res.data.code === 200) {
                this.activeStep++;
                this.$message.success("合同签署成功，三秒后返回主页");
                setTimeout(() => {
                  this.$router.push("/");
                }, 3000);
              } else {
                this.$message.error(res.data.message);
              }
            })
            .catch(err => {
              this.$message.error(err.message);
            });
        })
        .catch(() => {});
    },
    calculateStartDate() {
      let date = new Date();
      date.setDate(date.getDate() + 7);
      return date.toISOString().split("T")[0];
    },
    calculateEndDate() {
      let date = new Date();
      date.setDate(date.getDate() + 7);
      date.setFullYear(date.getFullYear() + 2);
      return date.toISOString().split("T")[0];
    },
    // 初始化
    init() {
      const canvas = this.$refs.signature;
      canvas.width = this.config.width; // 设置canvas的宽
      canvas.height = this.config.height; // 设置canvas的高
      // 设置一个边框
      canvas.style.border = "1px solid #000";
      // 存储canvas节点
      this.canvas = canvas;
      // 创建context对象
      this.ctx = canvas.getContext("2d");
      // 设置相应配置
      this.ctx.fillStyle = "transparent";
      this.ctx.lineWidth = this.config.lineWidth;
      this.ctx.strokeStyle = this.config.strokeStyle;
      this.ctx.lineCap = this.config.lineCap;
      this.ctx.lineJoin = this.config.lineJoin;
      // 绘制填充矩形
      this.ctx.fillRect(
        0, // x 轴起始绘制位置
        0, // y 轴起始绘制位置
        this.config.width, // 宽度
        this.config.height // 高度
      );
      // 创建鼠标/手势按下监听器
      canvas.addEventListener(
        this.mobileStatus ? "touchstart" : "mousedown",
        this.startDraw
      );
      // 创建鼠标/手势 弹起/离开 监听器
      canvas.addEventListener(
        this.mobileStatus ? "touchend" : "mouseup",
        this.cloaseDraw
      );
      canvas.addEventListener("mouseleave", this.closeDraw); // 鼠标离开时停止绘制
    },
    // 开始绘制
    startDraw(event) {
      this.points = []; // 每次开始绘制时清空点位
      const { offsetX, offsetY } = this.mobileStatus
        ? event.changedTouches[0]
        : event;
      // 初始化起始点
      this.client.offsetX = offsetX;
      this.client.offsetY = offsetY;
      // 存储当前画布的状态
      this.steps.push(
        this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height)
      );
      // 开始绘制路径
      this.ctx.beginPath();
      this.ctx.moveTo(this.client.offsetX, this.client.offsetY);
      // 标记正在绘制
      this.isDrawing = true;
      // 监听鼠标移动或触摸移动事件
      this.canvas.addEventListener(
        this.mobileStatus ? "touchmove" : "mousemove",
        this.draw
      );
      // 全局监听鼠标松手事件
      window.addEventListener(
        this.mobileStatus ? "touchend" : "mouseup",
        this.closeDraw
      );
    },
    // 绘制过程
    draw(event) {
      if (!this.isDrawing) return;
      const { offsetX, offsetY } = this.mobileStatus
        ? event.changedTouches[0]
        : event;
      this.points.push({ x: offsetX, y: offsetY }); // 记录当前点位
      // 绘制线条
      this.ctx.lineTo(offsetX, offsetY);
      this.ctx.stroke();
    },
    // 停止绘制
    closeDraw() {
      if (!this.isDrawing) return;
      // 停止绘制路径
      this.isDrawing = false;
      this.ctx.closePath();
      // 移除事件监听
      this.canvas.removeEventListener(
        this.mobileStatus ? "touchmove" : "mousemove",
        this.draw
      );
      window.removeEventListener(
        this.mobileStatus ? "touchend" : "mouseup",
        this.closeDraw
      );
    },
    // 键盘按下事件处理，监听退格键
    handleKeyDown(event) {
      if (event.key === "Backspace") {
        this.undo(); // 调用撤销方法
      }
    },
    // 撤销上一步操作
    undo() {
      if (this.steps.length > 0) {
        // 恢复到上一步的画布状态
        const lastStep = this.steps.pop(); // 取出最后一个状态
        this.ctx.putImageData(lastStep, 0, 0); // 恢复到上一步
      }
    },
    // 取消/清空画布
    clear() {
      // 清空当前画布上的所有绘制内容
      this.ctx.clearRect(0, 0, this.config.width, this.config.height);
      // 清空坐标
      this.points = [];
    },
    // 添加键盘监听
    addKeyListener() {
      window.addEventListener("keydown", this.handleKeyDown);
    },
    // 移除键盘监听
    removeKeyListener() {
      window.removeEventListener("keydown", this.handleKeyDown);
    },
    // 保存签名
    save() {
      // 判断是否有足够的点位（至少20个点）
      if (this.points.length < 20) {
        this.$message.error("签名不能为空，请至少绘制 20 个点！");
        return;
      }
      // 继续保存签名
      const baseFile = this.canvas.toDataURL(); // 转换为 base64 图片
      const filename = `${Date.now()}.png`; // 设置文件名
      const file = this.dataURLToFile(baseFile, filename); // 转换为文件对象
      // 上传签名
      this.uploadSignature(file);
      // this.dataUrlToPng(); // 将base64转成png图片并下载
      // this.dataToImg(); // 转成img显示签名
    },
    // img显示签名
    dataToImg() {
      // 转成base64
      const baseFile = this.canvas.toDataURL(); // 默认转成png格式的图片编码
      this.imgurl = baseFile;
    },
    // 将签名生成png图片
    dataUrlToPng() {
      // 将canvas上的内容转成blob流
      this.canvas.toBlob(blob => {
        // 获取当前时间并转成字符串，用来当做文件名
        const date = Date.now().toString();
        // 创建一个 a 标签
        const a = document.createElement("a");
        // 设置 a 标签的下载文件名
        a.download = `${date}.png`;
        // 设置 a 标签的跳转路径为 文件流地址
        a.href = URL.createObjectURL(blob);
        // 手动触发 a 标签的点击事件
        a.click();
        // 移除 a 标签
        a.remove();
      });
    },
    // 将 base64 数据转换为文件
    dataURLToFile(dataURL, filename) {
      const arr = dataURL.split(",");
      const mime = arr[0].match(/:(.*?);/)[1];
      const bstr = atob(arr[1]);
      let n = bstr.length;
      const u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], filename, { type: mime });
    },
    // 上传签名文件
    uploadSignature(file) {
      const formData = new FormData();
      formData.append("file", file);
      // 使用 axios 上传文件
      this.$axios
        .post("/upload", formData, {
          headers: {
            "Content-Type": "multipart/form-data"
          }
        })
        .then(response => {
          this.$message.success("上传成功");
          this.tenantInfo.autograph = response.data;
        })
        .catch(error => {
          this.messge.error(err.message);
        });
    }
  },
  watch: {
    activeStep(newStep) {
      if (newStep === 2) {
        // 确保 DOM 更新已完成
        this.$nextTick(() => {
          this.init();
          const canvas = this.$refs.signature;
          // 监听鼠标进入画布时添加键盘监听
          canvas.addEventListener("mouseenter", this.addKeyListener);
          // 监听鼠标离开画布时移除键盘监听
          canvas.addEventListener("mouseleave", this.removeKeyListener);
        });
      }
    }
  },
  beforeDestroy() {
    const canvas = this.$refs.signature;
    // 移除所有事件监听
    canvas.removeEventListener("mouseenter", this.addKeyListener);
    canvas.removeEventListener("mouseleave", this.removeKeyListener);
    window.removeEventListener("keydown", this.handleKeyDown);
  }
};
</script>
  
  <style scoped>
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.el-header {
  padding: 20px;
}
.el-main {
  padding: 20px;
  width: 1000px;
}
.next-button {
  margin-top: 20px;
  margin-left: 45%;
}
</style>
  